Case example Raw Data
Table
Data Preparation
There are 2 raw data available on the Github website, including “POC”
file and “PhillyCrimeSince2015” file. For “POC” file, we will select
random sample of 500 elements in a subset of the data set. In addition,
“PhillyCrimeSince2015” file will only select crime cases in 2023.
Moreover, if the latitude and longitude of the subdataset are missing,
the observation will be excluded.
# read final file
POC = read.csv("https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w07/POC.csv")
set.seed(123458)
#select random sample of 500 elements with NO replacement
kept_samp <- sample(1:nrow(POC), size = 500, replace = FALSE)
#select random sample of 500 rows from data frame
rand500_POC <- POC[kept_samp, ]
# write final data to csv file
write.csv(x = rand500_POC, file = "rand500_POC.csv", row.names = FALSE)
# read final file
Philly = read.csv("https://raw.githubusercontent.com/GUANTSERN-KUO/webcv/main/w07/PhillyCrimeSince2015.csv")
Philly$year <- year(as.POSIXct(Philly$date, format = "%m/%d/%Y %H:%M", tz = "EST") )
Philly2023 <- filter(Philly,year==2023) # create 2023data
Philly2023 <- filter(Philly2023,!is.na(lat)) # remove missing obs
Philly2023$ageColor<-gsub("Fatal","orange",as.character(Philly2023$fatal))
Philly2023$ageColor<-gsub("Nonfatal","darkred",as.character(Philly2023$ageColor))
PhDT <- Philly2023 %>%
dplyr::select(race, age,lng,lat,year)
POCDT <- rand500_POC %>%
dplyr::select(STATE ,county,ADDRESS,ZIPnew,diesel,dist.to.poc,ycoord,xcoord)
Descriptive Study
Purpose & Variables Relationship
The study primary focus on the distribution of diesel used in gas
station. Secondary understanding of the Mean distance between a gas
station and the Point of Compromised in PA. Finally, We want to
understand crime map in PA.
The below is the sub-data table for “PhillyCrimeSince2015”. However,
we will only use 5 variables and display data table as below.
- lng : longitude
- lat : latitude
The average age of offenders was 30.98, with the lowest age of
offenders being 2.
summary(PhDT$age)
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
2.00 21.00 29.00 30.98 37.00 87.00 23
The below is the sub-data table for “POC”. However, we will only use
8 variables and display data table as below.
- xcoord : longitude
- ycoord : latitude
- dist.to.poc : distance between a gas station and the nearest
POC
The average distance was 17.6, with the lowest distance being 0.12
and maximum distance being 47.7.
summary(POCDT$dist.to.poc)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.1292 5.6552 12.9125 17.6680 28.8643 47.7133
Distribution of
diesel used in gas station across U.S.
500 gas stations across U.S have been randomly selected from POC
data. 294 gas stations provide Diesel service, that is 58.8 percent of
selected gas stations. While 206 gas stations (41.2 percent) do not have
Diesel service.
piedata <- filter(rand500_POC,!is.na(diesel))
piedataf = data.frame(cate =as.vector(unique(piedata$diesel)),
freq = as.vector(table(piedata$diesel)))
## remove string X
piedataf$cate<-gsub("Y","Yes",as.character(piedataf$cate))
piedataf$cate<-gsub("N","No",as.character(piedataf$cate))
# define a color vector
colors <- c('rgb(211,94,96)', 'rgb(128,133,133)', 'rgb(144,103,167)')
# make a pie chart
plot_ly(piedataf,
labels = ~cate,
values = ~freq,
type = 'pie',
textposition = 'inside',
textinfo = 'label + percent',
insidetextfont = list(color = '#FFFFFF'),
#hoverinfo = 'text',
marker = list(colors = colors,
line = list(color = '#FFFFFF', width = 1)),
#The 'pull' attribute can also be used to create space between the sectors
showlegend = TRUE) %>%
layout(title = 'Distribution of diesel used in gas station',
xaxis = list(showgrid = FALSE, zeroline = FALSE,
showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE,
showticklabels = FALSE),
## margin of the plot
margin = list(
b = 50,
l = 100,
t = 120,
r = 50
))
The diesel service of
gas stations throughout the U.S
Looking at a the entire U.S. map, the supply of diesel fuel stations
in each region is fairly normal regardless east region, west region, and
central region. It is convenience for people to find diesel fuel
stations as there are plenty of gas stations within each county and
within short distance.
label.msg <- paste(paste("DIESEL:",rand500_POC$diesel),"\n")
# making static leaflet map
map0 <- leaflet(rand500_POC) %>%
addTiles() %>%
setView(lng=mean(rand500_POC$xcoord), lat=mean(rand500_POC$ycoord), zoom = 14) %>%
addRectangles(
lng1 = min(rand500_POC$xcoord), lat1 = min(rand500_POC$ycoord),
lng2 = max(rand500_POC$xcoord), lat2 = max(rand500_POC$ycoord),
#fillOpacity = 0.2,
fillColor = "transparent"
) %>%
fitBounds(
lng1 = min(rand500_POC$xcoord), lat1 = min(rand500_POC$ycoord),
lng2 = max(rand500_POC$xcoord), lat2 = max(rand500_POC$ycoord) ) %>%
addMarkers(~xcoord, ~ycoord, label = ~label.msg,
popup = ~paste(label.msg,
"<br>state:", STATE,
"<br>county:", county,
"<br>address", ADDRESS,
"<br>zip code", ZIPnew)
)
title <- tags$div( HTML('<font color = "darkred" size =4><b>Do gas stations have diesel service throughout the U.S.?</b></font>')
)
title2 <- tags$div( HTML('<font color = "red" size =0.5><b>500 randomly selected gas stations from the entire gas station dataset</b></font>')
)
###
map0 <- map0 %>%
addControl(title, position = "topright")
map0 <- map0 %>%
addControl(title2, position = "topright")
map0
The Mean distance
between a gas station and the Point of Compromised in PA 2023
Berks county has the highest mean distance (36.52) between a gas
station and the Point of Compromised. Lehigh county has the lowest mean
distance (7.27). The mean difference (29.25) between these two counties
is pretty high.
PA_POC <- filter(rand500_POC,STATE == "PA") # create 2015data
# Specify data frame
group_mean <- PA_POC %>%
# Specify group indicator, column, function
group_by(county) %>%
# Calculate the mean of the "Frequency" column for each group
summarise_at(vars(dist.to.poc),
list(Mean_Frequency = mean))
plot_ly(
data = group_mean,
x = ~county, # Horizontal axis
y = ~Mean_Frequency, # Vertical axis
color = ~factor(county), # must be a numeric factor
#text = ~Species,
# Show the species in the hover text
## using the following hovertemplate() to add the information of the
## Two numerical variables to the hover text.
### Use the following hover template to display more information
alpha = 0.6,
type = "scatter",
mode = "markers",
## graphic size
width = 700,
height = 500
)%>%
layout(
### Title
title =list(text = "Mean distance between a gas station and the nearest POC in PA 2023",
font = list(family = "Times New Roman", # HTML font family
size = 18,
color = "red")),
### legend
legend = list(title = list(text = 'county',
font = list(family = "Courier New",
size = 14,
color = "green")),
bgcolor = "ivory",
bordercolor = "navy",
groupclick = "togglegroup", # one of "toggleitem" AND "togglegroup".
orientation = "v" # Sets the orientation of the legend.
),
## margin of the plot
margin = list(
b = 100,
l = 100,
t = 100,
r = 50
),
## Background
plot_bgcolor ='#f7f7f7',
## Axes labels
xaxis = list(
title=list(text = 'County',
font = list(family = 'Arial')),
zerolinecolor = 'red',
zerolinewidth = 2,
gridcolor = 'white'),
yaxis = list(
title=list(text = 'Mean distance',
font = list(family = 'Arial')),
zerolinecolor = 'purple',
zerolinewidth = 2,
gridcolor = 'white')
)
Crime Map in PA
2023
Below crime map is showing the offenders in PA state in year 2023.
The amount of Non-fatal cases are higher than the amount of Fatal
cases.
ageColor <- Philly2023$ageColor
label.msg <- paste(paste("Race:", Philly2023$race),
paste("\n Age:",Philly2023$age),"\n")
#labels = cat(label.msg)
# making leaflet map
#labels = cat(label.msg)
# making leaflet map
# making leaflet map
map <- leaflet(Philly2023) %>%
addTiles() %>%
setView(lng=mean(Philly2023$lng), lat=mean(Philly2023$lat), zoom = 15) %>%
#OpenStreetMap, Stamen, Esri and OpenWeatherMap.
#addProviderTiles("Esri.WorldGrayCanvas") %>%
addProviderTiles(providers$Esri.WorldGrayCanvas) %>%
addCircleMarkers(
~lng,
~lat,
color = ageColor,
radius = ~ (Philly2023$age/10),
stroke = FALSE,
fillOpacity = 0.4,
label = ~label.msg) %>%
addLegend(position = "bottomright",
colors = c("orange","darkred"),
labels= c( "Fatal", "Nonfatal"),
title= "Crime Category",
opacity = 0.4)
title <- tags$div( HTML('<font color = "darkred" size =4><b>Pennsylvania crime map in 2023 </b></font>')
)
title2 <- tags$div( HTML('<font color = "red" size =0.5><b>The point size is proportional to the age of the criminal </b></font>')
)
###
EnhancedMap <- map %>%
addControl(title, position = "topright")
EnhancedMap <- EnhancedMap %>%
addControl(title2, position = "topright")
EnhancedMap
LS0tDQp0aXRsZTogIk1hcCBWaXN1bGF0aW9uIg0KYXV0aG9yOiAiR3VhbiBUc2VybiBLdW8iDQpkYXRlOiAiV2VzdCBDaGVzdGVyIFVuaXZlcnNpdHkiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICB0aGVtZTogbHVtZW4NCmVkaXRvcl9vcHRpb25zOg0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KDQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQovKiBUYWJsZSBvZiBjb250ZW50IC0gbmF2aWdhdGlvbiAqLw0KZGl2I1RPQyBsaSB7DQogICAgbGlzdC1zdHlsZTpub25lOw0KICAgIGJhY2tncm91bmQtY29sb3I6bGlnaHRncmF5Ow0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCiAgICBmb250LWZhbWlseTogQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZjsNCiAgICBjb2xvcjogIzc4MGMwYzsNCn0NCg0KDQovKiBUaXRsZSBmb250cyAqLw0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDI0cHg7DQogIGNvbG9yOiBkYXJrYmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogQXJpYWwsIEhlbHZldGljYSwgc2Fucy1zZXJpZjsNCiAgZm9udC12YXJpYW50LWNhcHM6IG5vcm1hbDsNCn0NCmg0LmF1dGhvciB7IA0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDQuZGF0ZSB7IA0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogZGFya2JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KLyogU2VjdGlvbiBoZWFkZXJzICovDQpoMSB7DQogICAgZm9udC1zaXplOiAyMnB4Ow0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgyIHsNCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyANCiAgICBmb250LXNpemU6IDE1cHg7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgew0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQovKiBEZWNvcmF0aW9uIG9mIGh5cGVybGlua3MgICovDQoNCi8qIHVudmlzaXRlZCBsaW5rICovDQphOmxpbmsgew0KICBjb2xvcjogZ3JlZW47DQp9DQoNCi8qIHZpc2l0ZWQgbGluayAqLw0KYTp2aXNpdGVkIHsNCiAgY29sb3I6IHB1cnBsZTsNCn0NCg0KLyogbW91c2Ugb3ZlciBsaW5rICovDQphOmhvdmVyIHsNCiAgY29sb3I6IHJlZDsNCn0NCg0KLyogc2VsZWN0ZWQgbGluayAqLw0KYTphY3RpdmUgew0KICBjb2xvcjogeWVsbG93Ow0KfQ0KPC9zdHlsZT4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgidGlkeXZlcnNlIikNCn0NCg0KaWYgKCFyZXF1aXJlKCJkcGx5ciIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZHBseXIiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJsdWJyaWRhdGUiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImx1YnJpZGF0ZSIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJsdWJyaWRhdGUiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJncGxvdHMiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdwbG90cyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJncGxvdHMiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJsZWFmbGV0IikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJsZWFmbGV0IikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImxlYWZsZXQiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJtYXBzIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJtYXBzIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoIm1hcHMiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJodG1sdG9vbHMiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImh0bWx0b29scyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJodG1sdG9vbHMiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJodG1sd2lkZ2V0cyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiaHRtbHdpZGdldHMiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiaHRtbHdpZGdldHMiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJsZWFmbGVnZW5kIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJsZWFmbGVnZW5kIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImxlYWZsZWdlbmQiKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZW9qc29uaW8iKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImdlb2pzb25pbyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJnZW9qc29uaW8iKQ0KfQ0KDQoNCmlmICghcmVxdWlyZSgiZ2FwbWluZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImdhcG1pbmRlciIpDQogICBsaWJyYXJ5KGdhcG1pbmRlcikNCn0NCmlmICghcmVxdWlyZSgidGlkeXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXIiKQ0KICAgbGlicmFyeSh0aWR5cikNCn0NCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgiY293cGxvdCIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJjb3dwbG90IikNCiAgIGxpYnJhcnkoY293cGxvdCkNCn0NCmlmICghcmVxdWlyZSgibGF0ZXgyZXhwIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImxhdGV4MmV4cCIpDQogICBsaWJyYXJ5KGxhdGV4MmV4cCkNCn0NCmlmICghcmVxdWlyZSgicGxvdGx5IikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogICBsaWJyYXJ5KHBsb3RseSkNCn0NCmlmICghcmVxdWlyZSgiZ2FwbWluZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImdhcG1pbmRlciIpDQogICBsaWJyYXJ5KGdhcG1pbmRlcikNCn0NCmlmICghcmVxdWlyZSgicG5nIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJwbmciKSAgICAgICAgICAgICAjIEluc3RhbGwgcG5nIHBhY2thZ2UNCiAgICBsaWJyYXJ5KCJwbmciKQ0KfQ0KaWYgKCFyZXF1aXJlKCJSQ3VybCIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiUkN1cmwiKSAgICAgICAgICAgICAjIEluc3RhbGwgUkN1cmwgcGFja2FnZQ0KICAgIGxpYnJhcnkoIlJDdXJsIikNCn0NCmlmICghcmVxdWlyZSgiY29sb3VycGlja2VyIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJjb2xvdXJwaWNrZXIiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiY29sb3VycGlja2VyIikNCn0NCmlmICghcmVxdWlyZSgiZ2dhbmltYXRlIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnZ2FuaW1hdGUiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2dhbmltYXRlIikNCn0NCmlmICghcmVxdWlyZSgiZ2lmc2tpIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnaWZza2kiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ2lmc2tpIikNCn0NCmlmICghcmVxdWlyZSgibWFnaWNrIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJtYWdpY2siKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgibWFnaWNrIikNCn0NCmlmICghcmVxdWlyZSgiZ3JEZXZpY2VzIikpIHsNCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJnckRldmljZXMiKSAgICAgICAgICAgICAgDQogICAgbGlicmFyeSgiZ3JEZXZpY2VzIikNCn0NCmlmICghcmVxdWlyZSgianBlZyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygianBlZyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJqcGVnIikNCn0NCmlmICghcmVxdWlyZSgiVkdBTSIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiVkdBTSIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJWR0FNIikNCn0NCmlmICghcmVxdWlyZSgiTUFTUyIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiTUFTUyIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJNQVNTIikNCn0NCmlmICghcmVxdWlyZSgibm5ldCIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygibm5ldCIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJubmV0IikNCn0NCmlmICghcmVxdWlyZSgiY2x1c3RlciIpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiY2x1c3RlciIpICAgICAgICAgICAgICANCiAgICBsaWJyYXJ5KCJjbHVzdGVyIikNCn0NCmlmICghcmVxdWlyZSgiZHBseXIiKSkgew0KICAgIGluc3RhbGwucGFja2FnZXMoImRwbHlyIikgICAgICAgICAgICAgIA0KICAgIGxpYnJhcnkoImRwbHlyIikNCn0NCmlmICghcmVxdWlyZSgib2RiYyIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJvZGJjIikNCiAgIGxpYnJhcnkob2RiYykNCn0NCmlmICghcmVxdWlyZSgiREJJIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoIkRCSSIpDQogICBsaWJyYXJ5KERCSSkNCn0NCmlmICghcmVxdWlyZSgiUlNRTGl0ZSIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJSU1FMaXRlIikNCiAgIGxpYnJhcnkoUlNRTGl0ZSkNCn0NCg0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KaWYgKCFyZXF1aXJlKCJkYXRhLnRhYmxlIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImRhdGEudGFibGUiKQ0KICAgbGlicmFyeShkYXRhLnRhYmxlKQ0KfQ0KDQoNCiMga25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSAiQzpcXFNUQTQ5MFxcdzA1IikNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFRSVUUsICAgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQSkNCg0KZGIgPC0gZGJDb25uZWN0KFJTUUxpdGU6OlNRTGl0ZSgpLCBkYm5hbWUgPSAic3FsLnNxbGl0ZSIpDQprbml0cjo6b3B0c19jaHVuayRzZXQoY29ubmVjdGlvbiA9ICJkYiIpDQoNCg0KYGBgDQoNCg0KIyBJbnRyb2R1Y3Rpb24gDQoNCkluIG9yZGVyIHRvIHByb3Blcmx5IGRlc2lnbiBhIG1hcCBkYXRhIHZpc3VhbGl6YXRpb24sIGl0IGlzIGltcG9ydGFudCB0byB1bmRlcnN0YW5kIHNvbWUgZ2VuZXJhbCB2aXN1YWxpemF0aW9uIHRoZW9yeTogdmFyaWFibGUgZGF0YSB0eXBlcy4gVmFyaWFibGUgZGF0YSB0eXBlcyBkZXRlcm1pbmUgdGhlIGRpZmZlcmVudCB2aXN1YWxpemF0aW9uIGVuY29kaW5ncyB0aGF0IGNhbiBiZSB1c2VkIGZvciB0aGUgZGF0YS4gV2Ugd2lsbCBpbnRyb2R1Y2Ugc2NhdHRlciBtYXAgd2l0aCBhIHByYWN0aWNhbCBleGFtcGxlLg0KDQoNCg0KIyBTY2F0dGVyIG1hcHMNCg0KU2NhdHRlciBtYXBzIHVzZSBkaXNjcmV0ZSBtYXJrZXJzIHRvIHJlcHJlc2VudCB0aGUgZ2VvZ3JhcGhpYyBsb2NhdGlvbiBvZiB0aGUgZGF0YSBhbmQgcmVxdWlyZSBsYXRpdHVkZSBhbmQgbG9uZ2l0dWRlIGNvb3JkaW5hdGVzIHRvIGJlIGdlbmVyYXRlZC4gV2hlbiB2aWV3aW5nIHRoZSB0YWJsZSwgeW91IHdpbGwgbm90aWNlIHRoYXQgaXQgY29udGFpbnMgZm91ciBwaWVjZXMgb2YgZ2VvZ3JhcGhpYyBpbmZvcm1hdGlvbjogY2l0eSwgc3RhdGUsIGxhdGl0dWRlLCBhbmQgbG9uZ2l0dWRlLg0KDQoNCmBgYHtyICxlY2hvID0gRkFMU0V9DQprbml0cjo6IGluY2x1ZGVfZ3JhcGhpY3MoInBpYy5naWYiKQ0KYGBgDQoNCg0KIyBDYXNlIGV4YW1wbGUgUmF3IERhdGEgVGFibGUgDQoNCiMjIERhdGEgUHJlcGFyYXRpb24NCg0KDQpUaGVyZSBhcmUgMiByYXcgZGF0YSBhdmFpbGFibGUgb24gdGhlIEdpdGh1YiB3ZWJzaXRlLCBpbmNsdWRpbmcgIlBPQyIgZmlsZSBhbmQgIlBoaWxseUNyaW1lU2luY2UyMDE1IiBmaWxlLiBGb3IgIlBPQyIgZmlsZSwgd2UgIHdpbGwgc2VsZWN0IHJhbmRvbSBzYW1wbGUgb2YgNTAwIGVsZW1lbnRzIGluIGEgc3Vic2V0IG9mIHRoZSBkYXRhIHNldC4gSW4gYWRkaXRpb24sICJQaGlsbHlDcmltZVNpbmNlMjAxNSIgZmlsZSB3aWxsIG9ubHkgc2VsZWN0IGNyaW1lIGNhc2VzIGluIDIwMjMuIE1vcmVvdmVyLCBpZiB0aGUgbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZSBvZiB0aGUgc3ViZGF0YXNldCBhcmUgbWlzc2luZywgdGhlIG9ic2VydmF0aW9uIHdpbGwgYmUgZXhjbHVkZWQuDQoNCg0KDQoNCmBgYHtyfQ0KDQojIHJlYWQgZmluYWwgZmlsZQ0KUE9DID0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9HVUFOVFNFUk4tS1VPL3dlYmN2L21haW4vdzA3L1BPQy5jc3YiKQ0KDQpgYGANCg0KYGBge3J9DQpzZXQuc2VlZCgxMjM0NTgpDQojc2VsZWN0IHJhbmRvbSBzYW1wbGUgb2YgNTAwIGVsZW1lbnRzIHdpdGggTk8gcmVwbGFjZW1lbnQNCmtlcHRfc2FtcCA8LSBzYW1wbGUoMTpucm93KFBPQyksIHNpemUgPSA1MDAsIHJlcGxhY2UgPSBGQUxTRSkNCg0KI3NlbGVjdCByYW5kb20gc2FtcGxlIG9mIDUwMCByb3dzIGZyb20gZGF0YSBmcmFtZQ0KcmFuZDUwMF9QT0MgPC0gUE9DW2tlcHRfc2FtcCwgXQ0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyB3cml0ZSBmaW5hbCBkYXRhIHRvIGNzdiBmaWxlDQp3cml0ZS5jc3YoeCA9IHJhbmQ1MDBfUE9DLCBmaWxlID0gInJhbmQ1MDBfUE9DLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCg0KYGBge3J9DQojIHJlYWQgZmluYWwgZmlsZQ0KUGhpbGx5ID0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9HVUFOVFNFUk4tS1VPL3dlYmN2L21haW4vdzA3L1BoaWxseUNyaW1lU2luY2UyMDE1LmNzdiIpDQpQaGlsbHkkeWVhciA8LSB5ZWFyKGFzLlBPU0lYY3QoUGhpbGx5JGRhdGUsIGZvcm1hdCA9ICIlbS8lZC8lWSAlSDolTSIsIHR6ID0gIkVTVCIpICkNCg0KDQpQaGlsbHkyMDIzIDwtIGZpbHRlcihQaGlsbHkseWVhcj09MjAyMykgICMgY3JlYXRlIDIwMjNkYXRhDQoNClBoaWxseTIwMjMgPC0gZmlsdGVyKFBoaWxseTIwMjMsIWlzLm5hKGxhdCkpICMgcmVtb3ZlIG1pc3Npbmcgb2JzDQoNCg0KDQpQaGlsbHkyMDIzJGFnZUNvbG9yPC1nc3ViKCJGYXRhbCIsIm9yYW5nZSIsYXMuY2hhcmFjdGVyKFBoaWxseTIwMjMkZmF0YWwpKQ0KDQpQaGlsbHkyMDIzJGFnZUNvbG9yPC1nc3ViKCJOb25mYXRhbCIsImRhcmtyZWQiLGFzLmNoYXJhY3RlcihQaGlsbHkyMDIzJGFnZUNvbG9yKSkNCg0KYGBgDQoNCmBgYHtyfQ0KDQpQaERUIDwtIFBoaWxseTIwMjMgJT4lDQogIGRwbHlyOjpzZWxlY3QocmFjZSwgYWdlLGxuZyxsYXQseWVhcikNCg0KUE9DRFQgPC0gcmFuZDUwMF9QT0MgJT4lDQogIGRwbHlyOjpzZWxlY3QoU1RBVEUgLGNvdW50eSxBRERSRVNTLFpJUG5ldyxkaWVzZWwsZGlzdC50by5wb2MseWNvb3JkLHhjb29yZCkNCmBgYA0KDQoNCiMjIERlc2NyaXB0aXZlIFN0dWR5IFB1cnBvc2UgJiBWYXJpYWJsZXMgUmVsYXRpb25zaGlwIA0KDQpUaGUgc3R1ZHkgcHJpbWFyeSBmb2N1cyBvbiB0aGUgZGlzdHJpYnV0aW9uIG9mIGRpZXNlbCB1c2VkIGluIGdhcyBzdGF0aW9uLiBTZWNvbmRhcnkgdW5kZXJzdGFuZGluZyBvZiB0aGUgTWVhbiBkaXN0YW5jZSBiZXR3ZWVuIGEgZ2FzIHN0YXRpb24gYW5kIHRoZSBQb2ludCBvZiBDb21wcm9taXNlZCBpbiBQQS4gRmluYWxseSwgV2Ugd2FudCB0byB1bmRlcnN0YW5kIGNyaW1lIG1hcCBpbiBQQS4NCg0KDQoNCg0KVGhlIGJlbG93IGlzIHRoZSBzdWItZGF0YSB0YWJsZSBmb3IgIlBoaWxseUNyaW1lU2luY2UyMDE1Ii4gSG93ZXZlciwgd2Ugd2lsbCBvbmx5IHVzZSA1IHZhcmlhYmxlcyBhbmQgZGlzcGxheSBkYXRhIHRhYmxlIGFzIGJlbG93Lg0KDQoNCi0gbG5nIDogbG9uZ2l0dWRlDQotIGxhdCA6IGxhdGl0dWRlDQoNCg0KDQpgYGB7ciBldmFsPXJlcXVpcmVOYW1lc3BhY2UoIkRUIiwgcXVpZXRseT1UUlVFKSwgZWNobz1GQUxTRX0NCkRUOjpkYXRhdGFibGUoKFBoRFQpLCBmaWxsQ29udGFpbmVyID0gRkFMU0UsIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSA2ICkgICkNCg0KYGBgDQpUaGUgYXZlcmFnZSBhZ2Ugb2Ygb2ZmZW5kZXJzIHdhcyAzMC45OCwgd2l0aCB0aGUgbG93ZXN0IGFnZSBvZiBvZmZlbmRlcnMgYmVpbmcgMi4NCg0KYGBge3J9DQpzdW1tYXJ5KFBoRFQkYWdlKQ0KDQpgYGANCg0KDQoNCg0KDQoNCg0KDQpUaGUgYmVsb3cgaXMgdGhlIHN1Yi1kYXRhIHRhYmxlIGZvciAiUE9DIi4gSG93ZXZlciwgd2Ugd2lsbCBvbmx5IHVzZSA4IHZhcmlhYmxlcyBhbmQgZGlzcGxheSBkYXRhIHRhYmxlIGFzIGJlbG93Lg0KDQoNCi0geGNvb3JkIDogbG9uZ2l0dWRlDQotIHljb29yZCA6IGxhdGl0dWRlDQotIGRpc3QudG8ucG9jIDogZGlzdGFuY2UgYmV0d2VlbiBhIGdhcyBzdGF0aW9uIGFuZCB0aGUgbmVhcmVzdCBQT0MNCmBgYHtyIGV2YWw9cmVxdWlyZU5hbWVzcGFjZSgiRFQiLCBxdWlldGx5PVRSVUUpLCBlY2hvPUZBTFNFfQ0KRFQ6OmRhdGF0YWJsZSgoUE9DRFQpLCBmaWxsQ29udGFpbmVyID0gRkFMU0UsIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSA2ICkgICkNCg0KYGBgDQoNClRoZSBhdmVyYWdlIGRpc3RhbmNlIHdhcyAxNy42LCB3aXRoIHRoZSBsb3dlc3QgZGlzdGFuY2UgYmVpbmcgMC4xMiBhbmQgbWF4aW11bSBkaXN0YW5jZSBiZWluZyA0Ny43Lg0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShQT0NEVCRkaXN0LnRvLnBvYykNCg0KYGBgDQoNCg0KDQojIyAgIERpc3RyaWJ1dGlvbiBvZiBkaWVzZWwgdXNlZCBpbiBnYXMgc3RhdGlvbiBhY3Jvc3MgVS5TLg0KDQo1MDAgZ2FzIHN0YXRpb25zIGFjcm9zcyBVLlMgaGF2ZSBiZWVuIHJhbmRvbWx5IHNlbGVjdGVkIGZyb20gUE9DIGRhdGEuIDI5NCBnYXMgc3RhdGlvbnMgcHJvdmlkZSBEaWVzZWwgc2VydmljZSwgdGhhdCBpcyA1OC44IHBlcmNlbnQgb2Ygc2VsZWN0ZWQgZ2FzIHN0YXRpb25zLiBXaGlsZSAyMDYgZ2FzIHN0YXRpb25zICg0MS4yIHBlcmNlbnQpIGRvIG5vdCBoYXZlIERpZXNlbCBzZXJ2aWNlLg0KDQoNCmBgYHtyfQ0KcGllZGF0YSA8LSBmaWx0ZXIocmFuZDUwMF9QT0MsIWlzLm5hKGRpZXNlbCkpDQoNCnBpZWRhdGFmID0gZGF0YS5mcmFtZShjYXRlID1hcy52ZWN0b3IodW5pcXVlKHBpZWRhdGEkZGllc2VsKSksIA0KICAgICAgICAgICAgICAgICAgICAgZnJlcSA9IGFzLnZlY3Rvcih0YWJsZShwaWVkYXRhJGRpZXNlbCkpKQ0KDQojIyByZW1vdmUgc3RyaW5nIFgNCnBpZWRhdGFmJGNhdGU8LWdzdWIoIlkiLCJZZXMiLGFzLmNoYXJhY3RlcihwaWVkYXRhZiRjYXRlKSkNCnBpZWRhdGFmJGNhdGU8LWdzdWIoIk4iLCJObyIsYXMuY2hhcmFjdGVyKHBpZWRhdGFmJGNhdGUpKQ0KDQoNCiMgZGVmaW5lIGEgY29sb3IgdmVjdG9yDQpjb2xvcnMgPC0gYygncmdiKDIxMSw5NCw5NiknLCAncmdiKDEyOCwxMzMsMTMzKScsICdyZ2IoMTQ0LDEwMywxNjcpJykNCiMgbWFrZSBhIHBpZSBjaGFydA0KcGxvdF9seShwaWVkYXRhZiwgDQogICAgICAgIGxhYmVscyA9IH5jYXRlLCANCiAgICAgICAgdmFsdWVzID0gfmZyZXEsIA0KICAgICAgICB0eXBlID0gJ3BpZScsDQogICAgICAgIHRleHRwb3NpdGlvbiA9ICdpbnNpZGUnLA0KICAgICAgICB0ZXh0aW5mbyA9ICdsYWJlbCArIHBlcmNlbnQnLA0KICAgICAgICBpbnNpZGV0ZXh0Zm9udCA9IGxpc3QoY29sb3IgPSAnI0ZGRkZGRicpLA0KICAgICAgICAjaG92ZXJpbmZvID0gJ3RleHQnLA0KICAgICAgICBtYXJrZXIgPSBsaXN0KGNvbG9ycyA9IGNvbG9ycywNCiAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICcjRkZGRkZGJywgd2lkdGggPSAxKSksDQogICAgICAgICAgICAgICAgICAgICAgI1RoZSAncHVsbCcgYXR0cmlidXRlIGNhbiBhbHNvIGJlIHVzZWQgdG8gY3JlYXRlIHNwYWNlIGJldHdlZW4gdGhlIHNlY3RvcnMNCiAgICAgICAgc2hvd2xlZ2VuZCA9IFRSVUUpICU+JSANCiAgICAgICAgIGxheW91dCh0aXRsZSA9ICdEaXN0cmlidXRpb24gb2YgZGllc2VsIHVzZWQgaW4gZ2FzIHN0YXRpb24nLA0KICAgICAgICAgICAgICAgIHhheGlzID0gbGlzdChzaG93Z3JpZCA9IEZBTFNFLCB6ZXJvbGluZSA9IEZBTFNFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSksDQogICAgICAgICAgICAgICAgeWF4aXMgPSBsaXN0KHNob3dncmlkID0gRkFMU0UsIHplcm9saW5lID0gRkFMU0UsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93dGlja2xhYmVscyA9IEZBTFNFKSwNCiAgICAgICAgICAgICAgICAgICAgICAjIyBtYXJnaW4gb2YgdGhlIHBsb3QNCiAgICAgIG1hcmdpbiA9IGxpc3QoDQogICAgICAgICAgICAgIGIgPSA1MCwNCiAgICAgICAgICAgICAgbCA9IDEwMCwNCiAgICAgICAgICAgICAgdCA9IDEyMCwNCiAgICAgICAgICAgICAgciA9IDUwDQogICAgICApKQ0KDQoNCmBgYCANCg0KDQojIyAgIFRoZSBkaWVzZWwgc2VydmljZSBvZiBnYXMgc3RhdGlvbnMgdGhyb3VnaG91dCB0aGUgVS5TDQoNCkxvb2tpbmcgYXQgYSB0aGUgZW50aXJlIFUuUy4gbWFwLCB0aGUgc3VwcGx5IG9mIGRpZXNlbCBmdWVsIHN0YXRpb25zIGluIGVhY2ggcmVnaW9uIGlzIGZhaXJseSBub3JtYWwgcmVnYXJkbGVzcyBlYXN0IHJlZ2lvbiwgd2VzdCByZWdpb24sIGFuZCBjZW50cmFsIHJlZ2lvbi4gSXQgaXMgY29udmVuaWVuY2UgZm9yIHBlb3BsZSB0byBmaW5kIGRpZXNlbCBmdWVsIHN0YXRpb25zIGFzIHRoZXJlIGFyZSBwbGVudHkgb2YgZ2FzIHN0YXRpb25zIHdpdGhpbiBlYWNoIGNvdW50eSBhbmQgd2l0aGluIHNob3J0IGRpc3RhbmNlLg0KDQoNCmBgYHtyfQ0KDQoNCmxhYmVsLm1zZyA8LSBwYXN0ZShwYXN0ZSgiRElFU0VMOiIscmFuZDUwMF9QT0MkZGllc2VsKSwiXG4iKQ0KICAgICAgICAgICAgICAgICANCg0KDQoNCiMgbWFraW5nIHN0YXRpYyBsZWFmbGV0IG1hcA0KbWFwMCA8LSBsZWFmbGV0KHJhbmQ1MDBfUE9DKSAlPiUNCiAgYWRkVGlsZXMoKSAlPiUgDQogIHNldFZpZXcobG5nPW1lYW4ocmFuZDUwMF9QT0MkeGNvb3JkKSwgbGF0PW1lYW4ocmFuZDUwMF9QT0MkeWNvb3JkKSwgem9vbSA9IDE0KSAlPiUNCiAgIGFkZFJlY3RhbmdsZXMoDQogICAgbG5nMSA9IG1pbihyYW5kNTAwX1BPQyR4Y29vcmQpLCBsYXQxID0gbWluKHJhbmQ1MDBfUE9DJHljb29yZCksDQogICAgbG5nMiA9IG1heChyYW5kNTAwX1BPQyR4Y29vcmQpLCBsYXQyID0gbWF4KHJhbmQ1MDBfUE9DJHljb29yZCksDQogICAgI2ZpbGxPcGFjaXR5ID0gMC4yLA0KICAgIGZpbGxDb2xvciA9ICJ0cmFuc3BhcmVudCIgDQogICAgKSAlPiUNCiAgZml0Qm91bmRzKA0KICAgIGxuZzEgPSBtaW4ocmFuZDUwMF9QT0MkeGNvb3JkKSwgbGF0MSA9IG1pbihyYW5kNTAwX1BPQyR5Y29vcmQpLA0KICAgIGxuZzIgPSBtYXgocmFuZDUwMF9QT0MkeGNvb3JkKSwgbGF0MiA9IG1heChyYW5kNTAwX1BPQyR5Y29vcmQpICkgJT4lDQogIGFkZE1hcmtlcnMofnhjb29yZCwgfnljb29yZCwgbGFiZWwgPSB+bGFiZWwubXNnLA0KICAgICAgICAgDQogICAgICAgICAgICAgcG9wdXAgPSB+cGFzdGUobGFiZWwubXNnLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPnN0YXRlOiIsIFNUQVRFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPmNvdW50eToiLCBjb3VudHksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+YWRkcmVzcyIsIEFERFJFU1MsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj56aXAgY29kZSIsIFpJUG5ldykNCiAgICAgICAgICAgICANCiAgICAgICAgICAgICAgKQ0KDQp0aXRsZSA8LSB0YWdzJGRpdiggSFRNTCgnPGZvbnQgY29sb3IgPSAiZGFya3JlZCIgc2l6ZSA9ND48Yj5EbyBnYXMgc3RhdGlvbnMgaGF2ZSBkaWVzZWwgc2VydmljZSB0aHJvdWdob3V0IHRoZSBVLlMuPzwvYj48L2ZvbnQ+JykNCikNCiB0aXRsZTIgPC0gdGFncyRkaXYoIEhUTUwoJzxmb250IGNvbG9yID0gInJlZCIgc2l6ZSA9MC41PjxiPjUwMCByYW5kb21seSBzZWxlY3RlZCBnYXMgc3RhdGlvbnMgZnJvbSB0aGUgZW50aXJlIGdhcyBzdGF0aW9uIGRhdGFzZXQ8L2I+PC9mb250PicpDQopDQojIyMNCm1hcDAgPC0gbWFwMCAlPiUNCiAgICAgYWRkQ29udHJvbCh0aXRsZSwgcG9zaXRpb24gPSAidG9wcmlnaHQiKQ0KDQptYXAwIDwtIG1hcDAgJT4lDQogICAgIGFkZENvbnRyb2wodGl0bGUyLCBwb3NpdGlvbiA9ICJ0b3ByaWdodCIpDQoNCiAgICAgIA0KICAgDQoNCiBtYXAwDQoNCmBgYA0KDQojIyAgIFRoZSBNZWFuIGRpc3RhbmNlIGJldHdlZW4gYSBnYXMgc3RhdGlvbiBhbmQgdGhlIFBvaW50IG9mIENvbXByb21pc2VkIGluIFBBIDIwMjMNCg0KQmVya3MgY291bnR5IGhhcyB0aGUgaGlnaGVzdCBtZWFuIGRpc3RhbmNlICgzNi41MikgYmV0d2VlbiBhIGdhcyBzdGF0aW9uIGFuZCB0aGUgUG9pbnQgb2YgQ29tcHJvbWlzZWQuIExlaGlnaCBjb3VudHkgaGFzIHRoZSBsb3dlc3QgbWVhbiBkaXN0YW5jZSAoNy4yNykuIFRoZSBtZWFuIGRpZmZlcmVuY2UgKDI5LjI1KSBiZXR3ZWVuIHRoZXNlIHR3byBjb3VudGllcyBpcyBwcmV0dHkgaGlnaC4NCg0KYGBge3J9DQoNClBBX1BPQyA8LSBmaWx0ZXIocmFuZDUwMF9QT0MsU1RBVEUgPT0gIlBBIikgICMgY3JlYXRlIDIwMTVkYXRhDQoNCg0KIyBTcGVjaWZ5IGRhdGEgZnJhbWUNCmdyb3VwX21lYW4gPC0gUEFfUE9DICU+JQ0KICAgICMgU3BlY2lmeSBncm91cCBpbmRpY2F0b3IsIGNvbHVtbiwgZnVuY3Rpb24NCiAgICBncm91cF9ieShjb3VudHkpICU+JQ0KICAgICMgQ2FsY3VsYXRlIHRoZSBtZWFuIG9mIHRoZSAiRnJlcXVlbmN5IiBjb2x1bW4gZm9yIGVhY2ggZ3JvdXANCiAgICBzdW1tYXJpc2VfYXQodmFycyhkaXN0LnRvLnBvYyksDQogICAgICAgICAgICAgICAgIGxpc3QoTWVhbl9GcmVxdWVuY3kgPSBtZWFuKSkNCiANCnBsb3RfbHkoDQogICAgZGF0YSA9IGdyb3VwX21lYW4sDQogICAgeCA9IH5jb3VudHksICAjIEhvcml6b250YWwgYXhpcyANCiAgICB5ID0gfk1lYW5fRnJlcXVlbmN5LCAgICMgVmVydGljYWwgYXhpcyANCiAgICBjb2xvciA9IH5mYWN0b3IoY291bnR5KSwgICMgbXVzdCBiZSBhIG51bWVyaWMgZmFjdG9yDQogICAgI3RleHQgPSB+U3BlY2llcywNCiAgDQogICAgICMgU2hvdyB0aGUgc3BlY2llcyBpbiB0aGUgaG92ZXIgdGV4dA0KICAgICAjIyB1c2luZyB0aGUgZm9sbG93aW5nIGhvdmVydGVtcGxhdGUoKSB0byBhZGQgdGhlIGluZm9ybWF0aW9uIG9mIHRoZQ0KICAgICAjIyBUd28gbnVtZXJpY2FsIHZhcmlhYmxlcyB0byB0aGUgaG92ZXIgdGV4dC4NCiAgICAgIyMjIFVzZSB0aGUgZm9sbG93aW5nIGhvdmVyIHRlbXBsYXRlIHRvIGRpc3BsYXkgbW9yZSBpbmZvcm1hdGlvbg0KICAgIA0KICAgICBhbHBoYSAgPSAwLjYsDQogICANCiAgICAgdHlwZSA9ICJzY2F0dGVyIiwNCiAgICAgbW9kZSA9ICJtYXJrZXJzIiwNCiAgICAgIyMgZ3JhcGhpYyBzaXplDQogICAgIHdpZHRoID0gNzAwLA0KICAgICBoZWlnaHQgPSA1MDANCg0KKSU+JQ0KICAgIGxheW91dCggIA0KICAgICAgIyMjIFRpdGxlIA0KICAgICAgdGl0bGUgPWxpc3QodGV4dCA9ICJNZWFuIGRpc3RhbmNlIGJldHdlZW4gYSBnYXMgc3RhdGlvbiBhbmQgdGhlIG5lYXJlc3QgUE9DIGluIFBBIDIwMjMiLCANCiAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICJUaW1lcyBOZXcgUm9tYW4iLCAgIyBIVE1MIGZvbnQgZmFtaWx5ICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDE4LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIpKSwgDQogICAgICAjIyMgbGVnZW5kDQogICAgICBsZWdlbmQgPSBsaXN0KHRpdGxlID0gbGlzdCh0ZXh0ID0gJ2NvdW50eScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250ID0gbGlzdChmYW1pbHkgPSAiQ291cmllciBOZXciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiZ3JlZW4iKSksDQogICAgICAgICAgICAgICAgICAgIGJnY29sb3IgPSAiaXZvcnkiLA0KICAgICAgICAgICAgICAgICAgICBib3JkZXJjb2xvciA9ICJuYXZ5IiwNCiAgICAgICAgICAgICAgICAgICAgZ3JvdXBjbGljayA9ICJ0b2dnbGVncm91cCIsICAjIG9uZSBvZiAgInRvZ2dsZWl0ZW0iIEFORCAidG9nZ2xlZ3JvdXAiLg0KICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiA9ICJ2IiAgIyBTZXRzIHRoZSBvcmllbnRhdGlvbiBvZiB0aGUgbGVnZW5kLg0KICAgICAgICAgICAgICAgICAgICApLA0KICAgICAgIyMgbWFyZ2luIG9mIHRoZSBwbG90DQogICAgICBtYXJnaW4gPSBsaXN0KA0KICAgICAgICAgICAgICBiID0gMTAwLA0KICAgICAgICAgICAgICBsID0gMTAwLA0KICAgICAgICAgICAgICB0ID0gMTAwLA0KICAgICAgICAgICAgICByID0gNTANCiAgICAgICksDQogICAgICAjIyBCYWNrZ3JvdW5kDQogICAgICBwbG90X2JnY29sb3IgPScjZjdmN2Y3JywgDQogICAgICAjIyBBeGVzIGxhYmVscw0KICAgICAgICAgICAgIHhheGlzID0gbGlzdCggDQogICAgICAgICAgICAgICAgICAgIHRpdGxlPWxpc3QodGV4dCA9ICdDb3VudHknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnQgPSBsaXN0KGZhbWlseSA9ICdBcmlhbCcpKSwNCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmVjb2xvciA9ICdyZWQnLCANCiAgICAgICAgICAgICAgICAgICAgemVyb2xpbmV3aWR0aCA9IDIsIA0KICAgICAgICAgICAgICAgICAgICBncmlkY29sb3IgPSAnd2hpdGUnKSwgDQogICAgICAgICAgICB5YXhpcyA9IGxpc3QoIA0KICAgICAgICAgICAgICAgICAgICB0aXRsZT1saXN0KHRleHQgPSAnTWVhbiBkaXN0YW5jZScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udCA9IGxpc3QoZmFtaWx5ID0gJ0FyaWFsJykpLA0KICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZWNvbG9yID0gJ3B1cnBsZScsIA0KICAgICAgICAgICAgICAgICAgICB6ZXJvbGluZXdpZHRoID0gMiwgDQogICAgICAgICAgICAgICAgICAgIGdyaWRjb2xvciA9ICd3aGl0ZScpDQoNCikNCg0KYGBgDQoNCg0KDQoNCg0KDQojIyAgIENyaW1lIE1hcCBpbiBQQSAyMDIzDQoNCkJlbG93IGNyaW1lIG1hcCBpcyBzaG93aW5nIHRoZSBvZmZlbmRlcnMgaW4gUEEgc3RhdGUgaW4geWVhciAyMDIzLiBUaGUgYW1vdW50IG9mIE5vbi1mYXRhbCBjYXNlcyBhcmUgaGlnaGVyIHRoYW4gdGhlIGFtb3VudCBvZiBGYXRhbCBjYXNlcy4gDQoNCg0KYGBge3J9DQoNCmFnZUNvbG9yIDwtIFBoaWxseTIwMjMkYWdlQ29sb3INCg0KDQpsYWJlbC5tc2cgPC0gcGFzdGUocGFzdGUoIlJhY2U6IiwgUGhpbGx5MjAyMyRyYWNlKSwgICAgDQogICAgICAgICAgICAgICAgICAgcGFzdGUoIlxuIEFnZToiLFBoaWxseTIwMjMkYWdlKSwiXG4iKQ0KDQojbGFiZWxzID0gY2F0KGxhYmVsLm1zZykNCiMgbWFraW5nIGxlYWZsZXQgbWFwDQojbGFiZWxzID0gY2F0KGxhYmVsLm1zZykNCiMgbWFraW5nIGxlYWZsZXQgbWFwDQoNCiMgbWFraW5nIGxlYWZsZXQgbWFwDQogbWFwIDwtIGxlYWZsZXQoUGhpbGx5MjAyMykgJT4lDQogIGFkZFRpbGVzKCkgJT4lIA0KICBzZXRWaWV3KGxuZz1tZWFuKFBoaWxseTIwMjMkbG5nKSwgbGF0PW1lYW4oUGhpbGx5MjAyMyRsYXQpLCB6b29tID0gMTUpICU+JQ0KICAjT3BlblN0cmVldE1hcCwgU3RhbWVuLCBFc3JpIGFuZCBPcGVuV2VhdGhlck1hcC4NCiAgI2FkZFByb3ZpZGVyVGlsZXMoIkVzcmkuV29ybGRHcmF5Q2FudmFzIikgJT4lDQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJEVzcmkuV29ybGRHcmF5Q2FudmFzKSAlPiUNCiAgYWRkQ2lyY2xlTWFya2VycygNCiAgICAgICAgICAgIH5sbmcsIA0KICAgICAgICAgICAgfmxhdCwNCiAgICAgICAgICAgIGNvbG9yID0gYWdlQ29sb3IsDQogICAgICAgICAgICByYWRpdXMgPSB+IChQaGlsbHkyMDIzJGFnZS8xMCksDQogICAgICAgICAgICBzdHJva2UgPSBGQUxTRSwgDQogICAgICAgICAgICBmaWxsT3BhY2l0eSA9IDAuNCwNCiAgICAgICAgICAgIGxhYmVsID0gfmxhYmVsLm1zZykgICU+JQ0KICBhZGRMZWdlbmQocG9zaXRpb24gPSAiYm90dG9tcmlnaHQiLCANCiAgICAgICAgICAgIGNvbG9ycyA9IGMoIm9yYW5nZSIsImRhcmtyZWQiKSwNCiAgICAgICAgICAgIGxhYmVscz0gYyggIkZhdGFsIiwgIk5vbmZhdGFsIiksDQogICAgICAgICAgICB0aXRsZT0gIkNyaW1lIENhdGVnb3J5IiwNCiAgICAgICAgICAgIG9wYWNpdHkgPSAwLjQpIA0KIA0KIA0KIA0KIA0KIHRpdGxlIDwtIHRhZ3MkZGl2KCBIVE1MKCc8Zm9udCBjb2xvciA9ICJkYXJrcmVkIiBzaXplID00PjxiPlBlbm5zeWx2YW5pYSBjcmltZSBtYXAgaW4gMjAyMyA8L2I+PC9mb250PicpDQopDQogdGl0bGUyIDwtIHRhZ3MkZGl2KCBIVE1MKCc8Zm9udCBjb2xvciA9ICJyZWQiIHNpemUgPTAuNT48Yj5UaGUgcG9pbnQgc2l6ZSBpcyBwcm9wb3J0aW9uYWwgdG8gdGhlIGFnZSBvZiB0aGUgY3JpbWluYWwgPC9iPjwvZm9udD4nKQ0KKQ0KIyMjDQpFbmhhbmNlZE1hcCA8LSBtYXAgJT4lDQogICAgIGFkZENvbnRyb2wodGl0bGUsIHBvc2l0aW9uID0gInRvcHJpZ2h0IikNCg0KRW5oYW5jZWRNYXAgPC0gRW5oYW5jZWRNYXAgJT4lDQogICAgIGFkZENvbnRyb2wodGl0bGUyLCBwb3NpdGlvbiA9ICJ0b3ByaWdodCIpDQoNCiAgICAgIA0KICAgDQoNCiBFbmhhbmNlZE1hcA0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=